
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import javax.swing.JOptionPane;

public class Binario {

    private RandomAccessFile lista;
    private File arquivo;
    private Inicio inicio;
    private final long bytes = 272;
    private final String caminho = "musica.dat";

    public Binario() {
        try {
            inicio = new Inicio();
            arquivo = new File(caminho);
            if (!arquivo.exists()) {
                arquivo.createNewFile();
            }
            lista = new RandomAccessFile(arquivo, "rw");
        } catch (FileNotFoundException e) {
            JOptionPane.showMessageDialog(null, "Arquivo da Lista não Encontrado");
        } catch (IOException e) {
        }
    }

    public void gravar(Musica musica) {
        try {
            if (lista.length() == 0) {
                musica.setPonteiroProximo(-1);
                inicio.setInicio(aloca(musica));
            } else {
                while (idExiste(musica.getId())) {
                    musica.setId(Integer.parseInt(JOptionPane.showInputDialog("Id ja existente, insira um novo...")));
                }
                lista.seek(inicio.getInicio() * bytes);
                long idAtual = lista.readLong();
                lista.seek(inicio.getInicio() * bytes);
                if (musica.getId() < idAtual) {
                    musica.setPonteiroProximo(inicio.getInicio());
                    inicio.setInicio(aloca(musica));
                } else {
                    long ponteiroAnterior = 0;
                    lista.seek(inicio.getInicio() * bytes);
                    long ponteiroAtual = inicio.getInicio();
                    idAtual = lista.readLong();
                    long ponteiroProximo = lista.readLong();
                    while (ponteiroProximo != -1 && musica.getId() >= idAtual) {
                        ponteiroAnterior = ponteiroAtual;
                        ponteiroAtual = ponteiroProximo;
                        lista.seek(ponteiroProximo * bytes);
                        idAtual = lista.readLong();
                        ponteiroProximo = lista.readLong();
                    }
                    if (ponteiroProximo != -1) {
                        musica.setPonteiroProximo(ponteiroProximo);
                        long endereco = aloca(musica);
                        lista.seek((ponteiroAnterior * bytes) + 8);
                        lista.writeLong(endereco);
                    } else {
                        musica.setPonteiroProximo(-1);
                        long endereco = aloca(musica);
                        lista.seek((ponteiroAnterior * bytes) + 8);
                        lista.writeLong(endereco);
                    }
                }
            }
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        }
    }

//  Quase Pronto ------------------  
    private boolean idExiste(long id) {
        boolean existe = false;
        try {
            if (id > 0) {
                long ponteiroAtual = inicio.getInicio();
                long idAtual = 0;
                long ponteiroProximo = 0;
                lista.seek(ponteiroAtual);
                while (ponteiroProximo != -1 && !existe) {
                    idAtual = lista.readLong();
                    ponteiroProximo = lista.readLong();
                    if (id == idAtual) {
                        existe = true;
                    } else {
                        lista.seek(ponteiroProximo);
                    }
                }
                lista.seek(0);
            }
        } catch (IOException e) {
        }
        return existe;
    }

    private long aloca(Musica musica) {
        long endereco = 0;
        try {
            endereco = lista.length() / bytes;
            lista.seek(endereco * bytes);
            lista.writeLong(musica.getId());
            lista.writeLong(musica.getPonteiroProximo());
            escreveString(musica.getNome(), lista.getFilePointer());
            escreveString(musica.getArtista(), lista.getFilePointer());
            escreveString(musica.getFormato(), lista.getFilePointer());
            lista.writeLong(musica.getDuracao());
            lista.writeLong(musica.getTamanho());
            inicio.inc();
        } catch (IOException e) {
        }
        return endereco;
    }

    //    Funcionando, não alterar -------------------------
    private void escreveString(String palavra, long seek) {
        StringBuffer buffer;
        if (palavra != null) {
            buffer = new StringBuffer(palavra);
        } else {
            buffer = new StringBuffer(40);
        }
        buffer.setLength(40);
        try {
            lista.seek(seek);
            lista.writeChars(buffer.toString());
        } catch (IOException e) {
        }
    }

//    Funcionando, não alterar -------------------------
    private String leString(long poteiro) {
        String retorno = "";
        try {
            char palavra[] = new char[40];
            char temp;
            lista.seek(poteiro);
            for (int i = 0; i < palavra.length; i++) {
                temp = lista.readChar();
                palavra[i] = temp;
            }
            retorno = new String(palavra).replace('\0', ' ');
        } catch (IOException e) {
        }
        return retorno;
    }

    public void listaLogico() {
        Musica musica = new Musica();
        StringBuilder builder = new StringBuilder();
        try {
            long ponteiro = inicio.getInicio();
            if (inicio.getTamanhoLista() > 0) {
                do {
                    lista.seek(ponteiro * bytes);
                    musica.setId(lista.readLong());
                    musica.setPonteiroProximo(lista.readLong());
                    musica.setNome(leString(lista.getFilePointer()));
                    musica.setArtista(leString(lista.getFilePointer()));
                    musica.setFormato(leString(lista.getFilePointer()));
                    musica.setDuracao(lista.readLong());
                    musica.setTamanho(lista.readLong());
                    ponteiro = musica.getPonteiroProximo();
                    builder.append(musica.toStringPonteiros());
                    builder.append("\n ------------ \n");
                } while (ponteiro != -1);
            } else {
                JOptionPane.showMessageDialog(null, "Lista Vazia");
            }
        } catch (IOException e) {
        }
        JOptionPane.showMessageDialog(null, builder.toString());
    }

    public void listaFisico() {
        Musica musica = new Musica();
        StringBuilder builder = new StringBuilder();
        try {
            if (lista.length() > 0) {
                long cont = 0;
                lista.seek(0);
                while (cont < lista.length()) {
                    musica.setId(lista.readLong());
                    musica.setPonteiroProximo(lista.readLong());
                    musica.setNome(leString(lista.getFilePointer()));
                    musica.setArtista(leString(lista.getFilePointer()));
                    musica.setFormato(leString(lista.getFilePointer()));
                    musica.setDuracao(lista.readLong());
                    musica.setTamanho(lista.readLong());
                    builder.append(musica.toStringPonteiros());
                    builder.append("\n ------------ \n");
                    cont += bytes;
                }
            } else {
                JOptionPane.showMessageDialog(null, "Lista Vazia");
            }
        } catch (IOException e) {
        }
        JOptionPane.showMessageDialog(null, builder.toString());
    }
}